﻿using System.Linq;
using System.Web;
using System.Web.Http;
using Enferno.Public.Web.Components.Server.Configuration;
using Enferno.Public.Web.Components.Server.ExceptionFilters;
using Enferno.Public.Web.Components.Server.Managers;
using Enferno.Public.Web.Components.Server.ViewModels;

namespace Enferno.Public.Web.Components.Server.Controllers
{
    [RoutePrefix("api/checkout"), 
    ComponentsControllerConfiguration]
    [ServiceModelFaultExceptionFilter]
    public class CheckoutController : ApiController
    {
        private readonly CheckoutManager _checkoutManager;

        public CheckoutController()
        {
            _checkoutManager = new CheckoutManager();
        }

        [Route("get")]
        [HttpGet]
        public CheckoutViewModelBase Get()
        {
            return _checkoutManager.GetCheckout();
        }

        [Route("{basketId}/setdelivery")]
        [HttpPost]
        public CheckoutViewModelBase SetDeliveryMethod(int basketId, DeliveryMethodModel deliveryMethod)
        {
            return _checkoutManager.SetDeliveryMethod(basketId, deliveryMethod.Id);
        }

        [Route("{basketId}/setpayment")]
        [HttpPost]
        public CheckoutViewModelBase SetPaymentMethod(int basketId, PaymentMethodModel paymentMethod)
        {
            return _checkoutManager.SetPaymentMethod(basketId, paymentMethod.Id);
        }

        [Route("{basketId}/updateprivateinformation")]
        [HttpPost]
        public PrivateCheckoutViewModel UpdatePrivateInformation(int basketId, UpdatePrivateInformationModel model)
        {
            return _checkoutManager.UpdatePrivateInformation(basketId, model.Buyer, model.Payer, model.ShipTo);
        }

        [Route("{basketId}/updatecompanyinformation")]
        [HttpPost]
        public CompanyCheckoutViewModel UpdateCompanyInformation(int basketId, UpdateCompanyInformationModel model)
        {
            return _checkoutManager.UpdateCompanyInformation(basketId, model.Buyer, model.Payer, model.ShipTo);
        }

        [Route("{basketId}/privatepurchase")]
        [HttpPost]
        public PaymentResponseViewModel PrivatePurchase(int basketId, PrivateCheckoutViewModel model)
        {
            var checkoutViewModel = _checkoutManager.UpdatePrivateInformation(basketId, model.Buyer,
                model.Payer, model.ShipTo);
            checkoutViewModel.OrderReference = model.OrderReference;
            return Purchase(basketId, checkoutViewModel);
        }

        [Route("{basketId}/companypurchase")]
        [HttpPost]
        public PaymentResponseViewModel CompanyPurchase(int basketId, CompanyCheckoutViewModel model)
        {
            var checkoutViewModel = _checkoutManager.UpdateCompanyInformation(basketId, model.Buyer,
                model.Payer, model.ShipTo);
            checkoutViewModel.OrderReference = model.OrderReference;
            return Purchase(basketId, checkoutViewModel);
        }

        private PaymentResponseViewModel Purchase(int basketId, CheckoutViewModelBase model)
        {
            //make sure that we update the order reference field on the basket item.
            _checkoutManager.UpdateOrderReference(basketId, model);

            //do the actual purchase
            var userAgent = HttpContext.Current.Request.UserAgent;
            var callerIp = HttpContext.Current.Request.UserHostAddress;

            var selectedPaymentMethodId = model.PaymentMethods.Single(paymentMethod => paymentMethod.IsSelected).Id;

            return _checkoutManager.Purchase(basketId, selectedPaymentMethodId, callerIp, userAgent);            
        }
    }

    public class PaymentMethodModel
    {
        public int Id { get; set; }
    }

    public class DeliveryMethodModel
    {
        public int Id { get; set; }
    }

    public class UpdatePrivateInformationModel
    {
        public CheckoutBuyerViewModel Buyer { get; set; }
        public CheckoutPrivatePayerViewModel Payer { get; set; }
        public CheckoutPrivateShipToViewModel ShipTo { get; set; }
    }

    public class UpdateCompanyInformationModel
    {
        public CheckoutBuyerViewModel Buyer { get; set; }
        public CheckoutCompanyPayerViewModel Payer { get; set; }
        public CheckoutCompanyShipToViewModel ShipTo { get; set; }
    }
}
